﻿using System;
using System.Collections.Generic;
using System.Linq.Expressions;
using System.Reflection;
using System.Web.Mvc;

namespace AutoClub.Support
{
    /// <summary>
    /// Extensiones para Collections deberia contener metodos capaces de agregar un valor a todo tipo de coleccion.
    /// </summary>
    public static class IEnumerableExtensions
    {
        /// <summary>
        /// Convierte una IEnumerable a una SelectList de MVC
        /// </summary>
        /// <returns></returns>
        public static SelectList ToDropDownList<T, TKey1, TKey2>(this IEnumerable<T> select, Expression<Func<T, TKey1>> valueProperty, Expression<Func<T, TKey2>> descriptionProperty)
        {
            return ToDropDownList(select, valueProperty, descriptionProperty, default(TKey1));
        }

        /// <summary>
        /// Convierte una IEnumerable a una SelectList de MVC
        /// </summary>
        /// <returns></returns>
        public static SelectList ToDropDownList<T, TKey1, TKey2>(this IEnumerable<T> select, Expression<Func<T, TKey1>> valueProperty, Expression<Func<T, TKey2>> descriptionProperty, TKey1 selectedItem)
        {
            string valuePropertyName = PropertyName(valueProperty);
            string textPropertyName = PropertyName(descriptionProperty);

            if ((selectedItem != null) && (!selectedItem.Equals(default(T))))
            {
                PropertyInfo selectedItemProperty = typeof(T).GetProperty(valuePropertyName);
                return new SelectList(select, valuePropertyName, textPropertyName, selectedItem);
            }
            else
                return new SelectList(select, valuePropertyName, textPropertyName);
        }

        /// <summary>
        /// Dada una expresion devuelve el nombre de la propiedad que se apunto.
        /// </summary>
        private static string PropertyName<T, TProperty>(Expression<Func<T, TProperty>> property)
        {
            var lambda = (LambdaExpression)property;

            MemberExpression memberExpression;
            if (lambda.Body is UnaryExpression)
            {
                var unaryExpression = (UnaryExpression)lambda.Body;
                memberExpression = (MemberExpression)unaryExpression.Operand;
            }
            else
                memberExpression = (MemberExpression)lambda.Body;

            return memberExpression.Member.Name;
        }
    }
}